from jili.core.printlog import print
from jili.core.pymsg import mohe as mh
import threading
subject_pos="pos_"
subject_fund="fund_"
subject_order="order_"
subject_trade="trade_"
subject_error="error_"
subject_login="login_"

subject_submitorder="submitorder_"
subject_cancelorder="cancelorder_"

class pos_live():
    def __init__(self,config,ip="127.0.0.1",auto_stop=["15:25","16:00"]):
        auto_stop=config.get("auto_stop",["15:25", "16:00"])
        trade_sub=config["trade_sub"]
        trade_pub=config["trade_pub"]
        self.mohe =mh(trade_sub, trade_pub, 1, isautorunrecv=True, isnoblock=False,
                  auto_stop=auto_stop)
        self.auto_stop=auto_stop
        self.ip=ip
        self.isloginsync = False
        self.islogin = False
        self.isready=False
        self.mkcode={}
        self.TIMEOUT = 60
        self.brokerid = ""
        self.investorid = ""
        self.channel = ""
        self.password = ""
        self.deal_tmp_data={
            "onpos":self.onpos,
            "onfund":self.onfund,
            "onorder":self.onorder
        }
        self.send_msg_list=[]
        self.onpos_ready=[]

        self.fund={}
        self.pos={}
        self.orders=[]
        self.working_orders={}
        self.trades=[]

    def add_pos_ready(self,func):
        self.onpos_ready.append(func)

    #pos_xtq
    def login(self,brokerid,investorid,password,channel="ctp.0",info={},issync_tradedata=True):
        rst=self.login_imp(brokerid,investorid,password,channel=channel,info=info,issync_tradedata=issync_tradedata)
        return rst
    def login_imp(self,brokerid,investorid,password,channel="ctp.0",info={},issync_tradedata=False):
        self.orders_book={}
        if issync_tradedata:
            self.TIMEOUT = 180
        else:
            self.TIMEOUT=60
        self.brokerid=brokerid
        self.investorid=investorid
        self.channel=channel
        self.password=password
        self.isloginsync=issync_tradedata
        self.mohe.subscribe(self.onpos, subject_pos, self.investorid)
        self.mohe.subscribe(self.onfund, subject_fund, self.investorid)
        self.mohe.subscribe(self.onorder, subject_order, self.investorid)
        self.mohe.subscribe(self.onerror, subject_error, self.investorid)
        self.mohe.subscribe(self.onlogin, subject_login, self.investorid)
        msg={"cmd":"login","password":password}
        msg.update(info)
        requestid=self.send_msg(msg)
        self.rst = dict(event=threading.Event(), requestid=requestid)
        self.rst['event'].clear()
        if self.rst['event'].wait(self.TIMEOUT):
            if self.rst['errorid'] == 0:
                del self.rst["event"]
                self.islogin = True
                # self.init_subtick()
            else:
                print(self.rst["errorid"],self.rst["errormsg"])
        else:
            print("超时")
        return self.islogin
    def onpos(self,msg):
        print("info", "__onpos", msg)
        data=msg["2"]
        for obj,v in data.items():
            if obj not in self.mkcode.keys():
                self.mkcode[obj]=list(v.values())[0]["mkcode"]
    def onfund(self,msg):
        print("info", "__onfund", msg)
        data=msg["2"]
        if not self.isready:
            self.isready=True
            for i in self.onpos_ready:
                i(self)
        self.fund=data

    def onorder(self,msg):
        print("info", "__onorder", msg)
        data=msg["2"]
        status = data["status"]
        oid=data["orderid"]
        self.orders.append(data)
        if status in ["canceled","parttraded","alltraded","rejected"]:
            if oid in self.working_orders.keys():
                del self.working_orders[oid]
        else:
            self.working_orders[oid] = data
    def onerror(self,msg):
        print("info", "__onerror", msg)
        data=msg["2"]
        if data["errorid"]==-1 and "no login" in data["errormsg"]:
            print("重新登录")
            rst=self.login(self.brokerid,self.investorid,self.password,self.channel)
            print(rst)
            if rst==True:
                print("重新请求",self.send_msg_list[-2])
                self.send_msg(self.send_msg_list[-2][1],self.send_msg_list[-2][0])
    def onlogin(self,msg):
        print("info", "__onlogin",msg)
        data=msg["2"]
        requestid=data["requestid"]
        IsLast=data["islast"]
        if requestid == self.rst['requestid'] and IsLast:
            print("debug","解除")
            if data['errorid'] == 0:
                self.islogin = True
            self.rst.update(data)
            self.rst['event'].set()
    def submit_order_imp(self,order):
        oid=self.get_uuid()
        order["orderid"]=oid
        order["cmd"]="submit_order"
        # data={"cmd":"submit_order","obj":obj,"bs":bs,"openclose":openclose,"price":price,"qty":qty,"orderid":oid,"mkcode":code,"ssid":ssid,"msg":msg}
        return self.send_msg(order,requestid=oid)

    # pos_xtq
    def cancel_order(self,orderid):
        if orderid in self.orders_book.keys():
            obj=self.orders_book[orderid]["obj"]
            mkcode=self.orders_book[orderid]["mkcode"]
            sysid=self.orders_book[orderid]["sysid"]
            data={"cmd":"cancel_order","orderid":orderid,"obj":obj,"mkcode":mkcode,"sysid":sysid}
            return self.send_msg(data)
        else:
            data = {"cmd": "cancel_order", "orderid": orderid}
            return self.send_msg(data)
    def send_msg(self, msg,requestid=None):
        if requestid is None:
            requestid = self.get_uuid()
        msg0= {"brokerid": self.brokerid, "investorid": self.investorid, "requestid": requestid}
        msg.update(msg0)
        self.send_msg_list.append((requestid,msg))
        print("info", "trade_adapter", self.channel, msg)
        self.mohe.send("trade_adapter", self.channel, msg)
        return requestid

    # pos_xtq
    def qry_info(self):
        #查询资金,持仓,委托
        self.send_msg({"cmd": "qry_info"})
    # pos_xtq
    def get_fund(self):
        self.send_msg({"cmd": "qry_fund"})
        return self.fund
    # pos_xtq
    def get_pos(self):
        self.send_msg({"cmd": "qry_pos"})
        return self.pos
    # pos_xtq
    def get_orders(self):
        self.send_msg({"cmd": "qry_order"})
        return self.orders
    # pos_xtq
    def get_trade(self):
        self.send_msg({"cmd": "qry_trade"})
        return self.trades